Плохо! Плохо!:  0
Показано с 1 по 2 из 2

Тема: [MV / MZ] Туториал по Гравигану

  1. #1
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию [MV / MZ] Туториал по Гравигану

    Туториал по Гравигану
    Версия 1.0 от 11.03.2022

    tl:dr, или "как это выглядит" в итоге
    Спойлер Видео:




    Вступление

    В процессе рассмотрения JS-библиотек для создания игр я вспомнил, что у эвентов в мейкере тоже есть переменные _x и _y (“BREAKING NEWS!”©), отвечающие за положение на карте. И что их изменение мгновенно меняет положение эвента. Выглядит это весьма странно, и я пытался вспомнить – а что это визуально напоминает? Напомнило мне это весьма глючный вариант поведения гравигана из серий игр Half-life и Portals.
    И я подумал, раз есть порталы, почему бы не сделать «гравиган»? А чем характеризуется гравиган их Халвы, упрощенно? Следующим:
    1. Можно поднять предмет, находясь от него в относительном удалении;
    2. Поднятый предмет следует за игроком, находясь близко перед ним;
    3. Поднятый предмет можно отпустить / кинуть куда-то;
    4. Поднять можно только один предмет.
    Можно ли такое поведение реализовать на мейкере, в принципе? Можно. А так как настроения и времени для разработки спец. плагина у меня нет, возник вопрос – можно ли это все сделать без плагинов? Можно! Не без минусов, но можно. Минусы решаемы, но…
    Минусы:
    А) Работает только в случае передвижения клавиатурой (и, возможно, геймпадом) – с мышкой все это НЕ РАБОТАЕТ!
    Б) «Захваченный» гравиганом эвент можно запульнуть за пределы карты.
    В) Иногда захватывается более дальний предмет.

    Все листинги скриптов приводятся в конце туториала.

    Спойлер Скриншоты по ссылке:


    Реализация

    0. Общие моменты
    Изначально я сделал гравиган на MZ, но на MV все делается точно также с одним небольшим исключением (демо на MV).
    Первое, что нам нужно – сделать на карте параллельное событие, отвечающее за всю логику гравигана; пока она работает – гравиган «фурычит». В этом событии мы будем получать координаты X и Y игрока, его направление, контролировать нажатие кнопок направлений движения и кнопки Enter для завхата/сброса предмета; Под «предметом» понимается первый из эвентов, находящийся на линии направления игрока (справа/слева/итд).
    Координаты игрока и направление нужны для того, что бы перемещать предмет на координаты ПЕРЕД игроком; направление также нужно, что бы корректно захватывать предметы по линии направления, а не вообще все.
    Таким образом, нам нужны 1 переключатель (захвачен предмет, или нет) и 4 переменные (координата X, Y, направление и одна переменная для эвента-предмета).

    1. Получение координат и направления
    Тут все просто и, скорее всего, все знают как это делается средствами мукера (можно и скриптом, но мне было лень). На скриншоте 1 указан данный процесс (координата Y и направление игрока берутся там же).

    2. Захват / сброс предмета
    Захват и сброс предмета происходят при помощи кнопки Enter, но не по нажатию ее, а по вызову. Тут и кроется отличие между MV и MZ, т.к. в MZ есть прямое условие на «вызов» кнопки, а у MV его нет и нужно использовать встроенную сриптовую команду.
    То есть, мы делаем условие со скриптом (Скриншот №2):
    Input.isTriggered('ok')
    И все, что далее – происходит в позитивном случае.

    2.1. Захват предмета
    Мы проверяем, включен ли переключатель завхата предмета.
    Если нет – происходит «захват», то есть, мы проверяем направление игрока и в зависимости от него ищем эвенты, что есть по линии верх/низ/лево/право – как на скриншоте №3. Нам нужен первый эвент в направлении (то есть ближайший к игрока), мы записываем его в переменную.
    Далее, проверив нужное направление, берем из переменной найденное событие и проверяем, не равно ли оно нулю. Если событие равно нулю, то поиск завершился безрезультатно – по направлению нет событий – и мы выключаем переключатель.
    Если же событие не равно нулю, то в зависимости от направления игрока мы меняем координаты события (так, чтоб оно стало ПЕРЕД игроком) и делаем его проходимым; проходимость события нужна, что бы игрок мог идти и эвент-предмет его не блокировал.
    Опционально можно давать звуковой сигнал, в зависимости от того, захватили предмет, или нет (по переключателю).

    2.2. Сброс предмета
    Если переключатель захвата предмета включен, то происходит «сброс».
    То есть мы скриптом пуляем эвент-предмет в сторону направления игрока; в данном случае, направление удобнее проверять в самом скрипте…как на скриншоте №5. Там же очищаем переменную, в которой хранился эвент-предмет, делаем его снова непроходимым и не забываем выключить переключатель! Также можно поставить какой-то звук.
    В этом же скрипте указывается дальность «пуляния» предмета!

    3. Перемещение предмета при движении
    В самом начале я писал, что нам нужно контролировать нажатие кнопок движения игрока. Зачем? Что бы перемещать событие перед игрком!
    Перемещается событие скриптом, причем скрипт одинаковый для всех кнопок (вверх/вниз/влево/вправо). Обратите внимание, скрипт выполняется при включенном переключателе, то есть, только когда предмет захвачен – см. скриншот №6.

    Заключение
    Ну вот и все. Туториал простой, демка есть. Механика забавная, но довольно таки бесполезная – аналог «броска предмета», а таких плагинов много.

    Спойлер Листинги скриптов:


    Условие для Entera:
    Код:
    Input.isTriggered('ok')
    Захват предметов – СЛЕВА:
    Код:
    let pX = $gameVariables.value(41);
    let pY = $gameVariables.value(42);
    
    let events = $gameMap.events();
    let eventsRightWay = events.filter(event => event._x >= pX && event._y === pY);
    
    let choosenEvent = eventsRightWay[0];
    $gameVariables.setValue(44, choosenEvent);
    Захват предметов – СПРАВА:
    Код:
    let pX = $gameVariables.value(41);
    let pY = $gameVariables.value(42);
    
    let events = $gameMap.events();
    let eventsLeftWay = events.filter(event => event._x <= pX && event._y === pY);
    
    let choosenEvent = eventsLeftWay[0];
    $gameVariables.setValue(44, choosenEvent);
    Захват предметов – СВЕРХУ:
    Код:
    let pX = $gameVariables.value(41);
    let pY = $gameVariables.value(42);
    
    let events = $gameMap.events();
    let eventsUpWay = events.filter(event => event._y <= pY && event._x === pX);
    
    let choosenEvent = eventsUpWay[0];
    $gameVariables.setValue(44, choosenEvent);
    Захват предметов – СНИЗУ:
    Код:
    let pX = $gameVariables.value(41);
    let pY = $gameVariables.value(42);
    
    let events = $gameMap.events();
    let eventsDownWay = events.filter(event => event._y >= pY && event._x === pX);
    
    let choosenEvent = eventsDownWay[0];
    $gameVariables.setValue(44, choosenEvent);
    Применение предмета ПОСЛЕ захвата (там же проверка на удачу захвата):
    Код:
    let pX = $gameVariables.value(41);let pY = $gameVariables.value(42);
    let pD = $gameVariables.value(43); let choosenEvent = $gameVariables.value(44);
    if(0 !== choosenEvent){
    if(2 == pD){ choosenEvent._x = pX; choosenEvent._y = pY + 1;
    }else if(4 == pD){ choosenEvent._x = pX - 1; choosenEvent._y = pY;
    }else if(6 == pD){ choosenEvent._x = pX + 1; choosenEvent._y = pY;
    }else if(8 == pD){ choosenEvent._x = pX; choosenEvent._y = pY - 1;
    }
    choosenEvent._through = true;
    }else{
    $gameSwitches.setValue(41, false);
    }
    Сброс захваченного предмета:
    Код:
    let pX = $gameVariables.value(41);let pY = $gameVariables.value(42);
    let pD = $gameVariables.value(43); let choosenEvent = $gameVariables.value(44);
    if(2 == pD){ choosenEvent._x = pX; choosenEvent._y = pY + 3;
    }else if(4 == pD){ choosenEvent._x = pX - 3; choosenEvent._y = pY;
    }else if(6 == pD){ choosenEvent._x = pX + 3; choosenEvent._y = pY;
    }else if(8 == pD){ choosenEvent._x = pX; choosenEvent._y = pY - 3;
    }
    $gameVariables.setValue(44, 0);
    choosenEvent._through = false;
    Скрипт перемещения предмета при движении игрока (одинаковый для вверх/вниз/влево/вправо):
    Код:
    let pX = $gameVariables.value(41);let pY = $gameVariables.value(42);
    let pD = $gameVariables.value(43); let choosenEvent = $gameVariables.value(44);
    
    if(2 == pD){
    choosenEvent._x = pX; choosenEvent._y = pY + 1;
    }else if(4 == pD){
    choosenEvent._x = pX - 1; choosenEvent._y = pY;
    }else if(6 == pD){
    choosenEvent._x = pX + 1; choosenEvent._y = pY;
    }else if(8 == pD){
    choosenEvent._x = pX; choosenEvent._y = pY - 1;
    }


    Спойлер Ссылки на демку (MV)...там же туториал по Порталам:

    В папке демки есть каталоги с pdf-файлами туториала и скринами.

    P.S:
    В связи с ситуацией, да и из-за того, что сайт мне доступен через день - отвечать быстро не смогу.
    Будут вопросы - пишите.

    P.P.S:
    Используя плагин на мышь и ._x и ._y эвента вполне реально сделать драг-н-дроп эвентов. Хотят такой плагин уже есть для MV(гуглите "mighty mouse").
    Последний раз редактировалось Darchan Kaen; 11.03.2022 в 20:02. Причина: Очепятка?

  2. #2
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    upd:
    Не упомянул в минусах, что по-умолчанию захватываются все эвенты и это может быть неудобно.

    Один из вариантов ограничения, какие эвенты захватывать, а какие - нет, это проверка локального переключателя.
    Делать это нужно в той части, которая отвечает за анализ результата захвата.
    В условие нужно дописать (и это позволит захватывать только те эвенты, у которых включен локальный переключатель "A"):
    Код:
    && true === $gameSelfSwitches.value([$gameMap._mapId, choosenEvent._eventId, 'A'])
    Спойлер Полный код скрипта условия с доп. проверкой локального переключателя:

    Код:
    let pX = $gameVariables.value(41);let pY = $gameVariables.value(42);
    let pD = $gameVariables.value(43); let choosenEvent = $gameVariables.value(44);
    if(0 !== choosenEvent && true === $gameSelfSwitches.value([$gameMap._mapId, choosenEvent._eventId, 'A'])){
      if(2 == pD){ choosenEvent._x = pX; choosenEvent._y = pY + 1;
      }else if(4 == pD){ choosenEvent._x = pX - 1; choosenEvent._y = pY;
      }else if(6 == pD){ choosenEvent._x = pX + 1; choosenEvent._y = pY;
      }else if(8 == pD){ choosenEvent._x = pX; choosenEvent._y = pY - 1;
      }
      choosenEvent._through = true;
    }else{
      $gameSwitches.setValue(41, false);
    }

    Вместо 'A' можно написать 'B' , 'C' или 'D' .

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Метки этой темы

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •  
[MV / MZ] Туториал по Гравигану